Application configuration files can also specify code bases. The <codeBase> element can be used to instruct the CLR to probe for dependent assemblies located at arbitrary locations (such as network end points, or an arbitrary machine path outside a client’s application directory).
If the value assigned to a <codeBase> element is located on a remote machine, the assembly will be downloaded on demand to a specific directory in the GAC termed the download cache. Given what you have learned about deploying assemblies to the GAC, it should make sense that assemblies loaded from a <codeBase> element will need to be assigned a strong name (after all, how else could the CLR install remote assemblies to the GAC?). If you are interested, you can view the content of your machine’s download cache by supplying the /ldl option to gacutil.exe:
gacutil /ldl
Note Technically speaking, the <codeBase> element can be used to probe for assemblies that do not have a strong name. However, the assembly’s location must be relative to the client’s application directory (and thus is little more than an alternative to the <privatePath> element).
To see the <codeBase> element in action, create a Console Application named CodeBaseClient, set a reference to CarLibrary.dll version 2.0.0.0, and update the initial file as follows:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using CarLibrary; namespace CodeBaseClient { class Program { static void Main(string[] args) { Console.WriteLine("***** Fun with CodeBases *****"); SportsCar c = new SportsCar(); Console.WriteLine("Sports car has been allocated."); Console.ReadLine(); } } }
Given that CarLibrary.dll has been deployed to the GAC, you are able to run the program as is. However, to illustrate the use of the <codeBase> element, create a new folder under your C: drive (perhaps C:\MyAsms) and place a copy of CarLibrary.dll version 2.0.0.0 into this directory.
Now, add an App.config file to the CodeBaseClient project (as explained earlier in this chapter) and author the following XML content (remember that your .publickeytoken value will differ; consult your GAC as required):
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name=" CarLibrary" publicKeyToken="33A2BC294331E8B9" /> <codeBase version="2.0.0.0" href="file:///C:/MyAsms/CarLibrary.dll" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
As you can see, the <codeBase> element is nested within the <assemblyIdentity> element, which makes use of the name and publicKeyToken attributes to specify the friendly name as associated publicKeyToken values. The <codeBase> element itself specifies the version and location (via the href property) of the assembly to load. If you were to delete version 2.0.0.0 of CarLibrary.dll from the GAC, this client would still run successfully, as the CLR is able to locate the external assembly under C:\MyAsms.
Note If you place assemblies at random locations on your development machine, you are in effect re-creating the system registry (and the related DLL hell), given that if you move or rename the folder containing your binaries, the current bind will fail. With that in mind, use <codeBase> with caution.
The <codeBase> element can also be helpful when referencing assemblies located on a remote networked machine. Assume you have permission to access a folder located at http://www.MySite.com. To download the remote *.dll to the GAC’s download cache on your local machine, you could update the <codeBase> element as follows:
<codeBase version="2.0.0.0" href="http://www.MySite.com/Assemblies/CarLibrary.dll" />
Source Code The CodeBaseClient application can be found under the Chapter 14 subdirectory.